/**==============================================================================
            Copyright (c) 2013 Moritz Hader, Marcel Schrder
            All Rights Reserved.

	@file  Translator.java

	@brief Translates between JSON Strings in determined formats and the browser 
	internal object representation of certain information.

This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
==============================================================================*/
package de.ibm.dhbw.backing.dataHolding;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Logger;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


/**
 * @author Marcel Schroeder - marcel_schroeder89@hotmail.com
 */
public class Translator {
	
	private static final Logger Log = Logger.getLogger(Translator.class.getCanonicalName());
	//----------- Properties and Constructor -----------//

	private float markerRadius;
	private HashMap<Integer, Marker> markersMap;
	private Marker[] requestedMarkers;
	private ElementManager elMa;						//refreshMarkers

	public Translator(float markerRadius, ElementManager elMa) {
		this.markerRadius = markerRadius;
		this.elMa = elMa;
		this.markersMap = new HashMap<Integer, Marker>();
	}
	
	
	//----------- Internal Methods -----------//

	//ready
	//successfully tested
	/**
	 * Searches for a certain Marker in the list of the in the last request used Markers by its x- and y-position.
	 * @param markerX X-position (IS) of the searched marker
	 * @param markerY Y-position (IS) of the searched marker
	 * @return The searched marker; if not found the first Marker of overall Marker-HashMap from the ElementManager, the default Marker with id 0, is returned
	 */
	private Marker findMarker(float markerX, float markerY) {
		Log.info("Markers in Translator - findMarker: Markers in List: " + this.markersMap.size());
	 	Marker marker = this.markersMap.get(0);
	 	for(Marker n : this.requestedMarkers) {
	 		if(n.getIS_posX() == markerX && n.getIS_posY() == markerY) {
	 			marker = n;
	 		}
	 	}
	 	return marker;
	}
	
	
	//----------- External Methods -----------//
	
	//ready
	//successfully tested
	/**
	 * Parses a JSON String from the IS containing Marker information and creates the according Marker objects.
	 * @param input A JSON String in a determined format containing Marker information
	 * @return An HashMap of Markers containing the created Marker objects.
	 */
	protected HashMap<Integer, Marker> getMarkersOutOfJSONMap(String input) {
		HashMap<Integer, Marker> markers = new HashMap<Integer, Marker>();
		try {
			JSONArray outerArray = new JSONArray(input);
			for(int i=0; i<outerArray.length(); i++) {
				JSONObject innerObject = outerArray.getJSONObject(i);
				markers.put(innerObject.getInt("id"), new Marker(innerObject.getInt("id"), (float)innerObject.getDouble("x"), (float)innerObject.getDouble("y")));
			}
		} catch (JSONException e) {
			Log.severe("JSONException in Translator - getMarkersOutOfJSON");
			e.printStackTrace();
		}
		this.markersMap = markers;
		return markers;
	}
	
	//not finally ready
	//successfully tested so far
	//TODO implement full type <-> ElementObject assignment
	/**
	 * Parses a JSON String from the IS containing ElementObject information and creates the according StaticElementObject and DynamicElementObject objects.
	 * @param input A JSON String in a determined format containing ElementObject information
	 * @return An ArrayList of ElementObjects containing the created StaticElementObject and DynamicElementObject objects.
	 */
	protected ArrayList<ElementObject> getElementsOutOfJSON(String input) {
		ArrayList<ElementObject> elements = new ArrayList<ElementObject>();
		try {
			JSONArray outerArray = new JSONArray(input);
			for(int i=0; i<outerArray.length(); i++) {
				JSONObject outerObject = outerArray.getJSONObject(i);
				
				Marker marker = this.findMarker((float)outerObject.getDouble("x"), (float)outerObject.getDouble("y"));
				
				// /*<<<TEST AUSGABE>>>*/ 
				Log.info("Objects found for Marker at position x:" + outerObject.getDouble("x") + "|y:" + outerObject.getDouble("y"));
				
				JSONArray innerArray = outerObject.getJSONArray("found");
				
				for(int j=0; j<innerArray.length(); j++) {
					JSONObject innerObject = (JSONObject) innerArray.getJSONObject(j);
					
					/*<<<TEST AUSGABE>>>*/ 
					Log.info("==> Element at position x:" + innerObject.getDouble("x") + "|y:" + innerObject.getDouble("y") /* + " of type: " + innerObject.getInt("type")*/);
					
					if(innerObject.getInt("type") < 100) {
						elements.add(new DynamicElementObject(innerObject.getInt("id"), innerObject.getInt("type"), (float)innerObject.getDouble("x"), (float)innerObject.getDouble("y"), (float)innerObject.getDouble("xdir"), (float)innerObject.getDouble("ydir"), marker));
					} else {
						elements.add(new StaticElementObject(innerObject.getInt("id"), innerObject.getInt("type"), (float)innerObject.getDouble("x"), (float)innerObject.getDouble("y"), (float)innerObject.getDouble("xdir"), (float)innerObject.getDouble("ydir"), (short)42, marker));
					}
				}
			}
		} catch (JSONException e) {
			Log.severe("JSONException in Translator - getElementsOutOfJSON");
			e.printStackTrace();
		}
		return elements;
	}
	
	//ready
	//successfully tested
	/**
	 * Generates a JSON String in a determined format out of the information of the given markers
	 * @param markers An Array of Marker objects
	 * @return The generated JSON String
	 */
	protected String getJSONOutOfMarkers(Marker[] markers) {
		/*new Map*/ this.requestedMarkers = markers;
		JSONArray outerArray = new JSONArray();
		for(Marker i : markers) {
			JSONObject innerObject = new JSONObject();
			try {
				innerObject.put("r", this.markerRadius);
				innerObject.put("y", i.getIS_posY());
				innerObject.put("x", i.getIS_posX());
				outerArray.put(innerObject);
			} catch (JSONException e) {
				Log.severe("JSONException in Translator - getJSONOutOfMarkers");
				e.printStackTrace();
			}
		}
		return outerArray.toString();
	}
	
	/*new ID*/ protected String getJSONOutOfMarkersID(int[] markerIds) {
	/*new ID*/ 	Marker[] markers = new Marker[markerIds.length];
	/*new ID*/ 	JSONArray outerArray = new JSONArray();
	/*new ID*/ 	int i = 0;
	/*new ID*/ 	for(int mI : markerIds) {
					markers[i] = this.markersMap.get(mI);
					JSONObject innerObject = new JSONObject();
					try {
						innerObject.put("r", this.markerRadius);
						innerObject.put("y", markers[i].getIS_posY());
						innerObject.put("x", markers[i].getIS_posX());
						outerArray.put(innerObject);
						i++;
					} catch (JSONException e) {
						Log.severe("JSONException in Translator - getJSONOutOfMarkers");
						e.printStackTrace();
					}
	/*new ID*/ 	}
				this.requestedMarkers = markers;
	/*new ID*/ 	return outerArray.toString();
	/*new ID*/ }
	
	
	//----------- Simple Getter and Setter -----------//

	protected float getMarkerRadius() {
		return this.markerRadius;
	}
	
	protected void setMarkerRadius(float markerRadius) {
		this.markerRadius = markerRadius;
	}
}